package com.start.model;

import com.star.common.ConfigFactory;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import net.spy.memcached.MemcachedClient;
import org.apache.log4j.Logger;

public class MemcachedModel {

    private static final Logger logger = Logger.getLogger(MemcachedModel.class);

    private static final String host = ConfigFactory.getParam("memcached", "host");
    private static final int port = Integer.parseInt(ConfigFactory.getParam("memcached", "port"));
    private static long LAST_FAIL_TIMESTAMP = 0;
    private static final int RETRY_INTERVAL = 1 * 1000 * 20;
    private static MemcachedClient c = null;
    static DateFormat fmt = new SimpleDateFormat("HH:mm:ss.SSS");

    static {
        try {
//            c = new MemcachedClient(new InetSocketAddress(host, port));
//            c = new MemcachedClient( new ConnectionFactoryBuilder().setProtocol(Protocol.BINARY).build(), AddrUtil.getAddresses(host + ":" + port));
        } catch (Exception ex) {
            logger.error("MemcachedModel.init: " + ex.getMessage(), ex);
            markAsFail();
        }
    }
    public static void deleteCache(String key) {
        try {
            if (shouldRetryNow()) {
                c.delete(key);
            }
        } catch (Exception ex) {
            logger.error("MemcachedModel.deleteCache: " + ex.getMessage(), ex);
            markAsFail();
        }
    }
    public static void flushCache() {
        try {
            if (shouldRetryNow()) {
                c.flush();
            }
        } catch (Exception ex) {
            logger.error("MemcachedModel.flushCache: " + ex.getMessage(), ex);
            markAsFail();
        }
    }

    public static void clearCache(String listKey) {
        List<String> keys = getListKey(listKey);
        for (String key : keys) {
            try {
                logger.info("to delete key: " + key + " value: " + c.get(key));
                if (shouldRetryNow() && key!=null) {
//                    c.delete(key);
                    c.delete(key);
                }
            } catch (Exception ex) {
                logger.error("MemcachedModel.clearCache: " + ex.getMessage(), ex);
                markAsFail();
            }
        }
        c.delete(listKey);
    }

    public static void setCache(String key, Object value, int CACHE_TIME) {
        if(value == null) return;
        try {
            if (shouldRetryNow()) {
                c.set(key, CACHE_TIME, value);
                LAST_FAIL_TIMESTAMP = 0;
            }
        } catch (Exception ex) {
            logger.error("MemcachedModel.setCache: " + ex.getMessage(), ex);
            markAsFail();
        }
    }

    public static Object getCache(String key) {
        try {
//            if (shouldRetryNow()) {
            Object myObj=null;
            Future<Object> f=    c.asyncGet(key);

            myObj = f.get(1, TimeUnit.SECONDS);
            
            LAST_FAIL_TIMESTAMP = 0;
                if(myObj!=null){
                    return myObj;
                }else{
                    c.touch(key, 1);
                }
//            }
        } catch (Exception ex) {
            logger.error("MemcachedModel.getCache: " + ex.getMessage(), ex);
            markAsFail();
        }
        return null;
    }

    private static void markAsFail() {
        LAST_FAIL_TIMESTAMP = System.currentTimeMillis();
    }

    private static boolean shouldRetryNow() {
        
        return true;
        
//        long current = System.currentTimeMillis();
//        if (current - LAST_FAIL_TIMESTAMP > RETRY_INTERVAL) {
//            return true;
//        }
//        logger.info("Retry in " + ((RETRY_INTERVAL - current + LAST_FAIL_TIMESTAMP) / 1000) + " seconds");
//        return false;
    }
    public static void setListKey(String key, List<String> listKey, int time){
        deleteCache(key);
        setCache(key, listKey, time);
    }
    public static List<String> getListKey(String key){
        Object val= getCache(key);
        List<String> lstKey = new ArrayList<>();
        if(val!=null){
            lstKey = (List<String>) val;
        }
        return lstKey;
    }
}
